home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 Spring / macformat-077.iso / Shareware Plus / Development / SpriteWorld 2.2 Extra Demos / Maze Game / Modified Scrolling - Open! / Scrolling Demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-12-31  |  25.6 KB  |  927 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. // Scrolling Demo.c - Modified version
  3. //
  4. // By Vern Jensen. Created sometime in 1997
  5. ///--------------------------------------------------------------------------------------
  6.  
  7.  
  8. #include <SWFPSReport.h>
  9. #include <SWIncludes.h>
  10. #include <SWGameUtils.h>
  11.  
  12. #include "SWApplication.h"
  13. #include "Scrolling Demo.h"
  14.  
  15.  
  16. #define kRequireDiamondsToExit        false        // If true, you must collect all diamonds to exit
  17.  
  18. #define kMaxWindowWidth                640            // User can expand window to this size
  19. #define kMaxWindowHeight            480
  20.  
  21. #define    kInterlacedMode                false        // Turns Interlaced mode on/off
  22. #define kSyncToVBL                    false        // Sync SpriteWorld to VBL?
  23. #define kMaxFPS                        20            // Set to 0 for unrestricted speed
  24.     
  25. #define    kSpriteMoveDelta            20            // Try 5, 10, 20, or 40
  26. #define kDiamondSpace                8            // How far apart the diamonds are spaced
  27.                                                 // (try 1!)
  28.  
  29. #define kSpriteMoveDistance            80            // How far the sprite can move from
  30.                                                 // the center of the screen, in pixels.
  31.                                                 // Try making this value higher!
  32.  
  33.     // Number of ticks to wait before changing tile image; 0 = change every frame
  34. #define kExitFrameRate                10
  35. #define kDiamondFrameRate            8            // How often diamond tiles change frames
  36. #define kWallFrameRate                120            // How often wall changes frames
  37.  
  38. #define    kSpritePictResID            202
  39. #define kTilePictResID                200
  40. #define kTileWidth                    40
  41. #define kTileHeight                    40
  42.  
  43. #define kStartRow                    4            // Starting position of sprite
  44. #define kStartCol                    5            // in tile col and row
  45.  
  46.  
  47. #define    kLeftArrowKey                0x7B
  48. #define    kRightArrowKey                0x7C
  49. #define    kDownArrowKey                0x7D
  50. #define    kUpArrowKey                    0x7E
  51.  
  52. #define    kLeftKeyPad                    0x56
  53. #define    kRightKeyPad                0x58
  54. #define    kDownKeyPad                    0x54
  55. #define    kUpKeyPad                    0x5B
  56.  
  57. #define kEscKey                        0x35
  58.  
  59.  
  60. #define kNoKey                        0
  61. #define kLeftKey                    1
  62. #define kUpKey                        2
  63. #define kRightKey                    3
  64. #define kDownKey                    4
  65.  
  66.  
  67. enum tileIDs
  68. {
  69.     kFirstWallTile,
  70.     kLastWallTile = kFirstWallTile+13,
  71.     kFirstGrassTile,
  72.     kLastGrassTile = kFirstGrassTile+2,
  73.     kBlackTile,
  74.     kDiamondTile,
  75.     kDiamondTile2,
  76.     kLastDiamondTile,
  77.     kFirstExitTile,
  78.     kLastExitTile,
  79.     
  80.     kMaxNumTiles
  81. };
  82.  
  83.  
  84.  
  85. /***********/
  86. /* Globals */
  87. /***********/
  88.  
  89. SpriteWorldPtr        gSpriteWorldP;
  90. SpriteLayerPtr        gSpriteLayerP;
  91. SpriteLayerPtr        gMouseSpriteLayerP;
  92. TileMapStructPtr    gTileMapStructP;
  93. TileMapPtr            gTileMap;
  94. SpritePtr            gSimpleSpriteP, gDiamondMeterSpriteP, gMouseSpriteP;
  95. DrawProcPtr            gSpriteDrawProc;
  96. DrawProcPtr            gScreenDrawProc;
  97. DoubleDrawProcPtr    gDoubleRectDrawProc;
  98. WindowPtr            gWindowP;
  99. Rect                gScreenMidRect;
  100. Boolean                gDone = false, gSpriteHitExit = false;
  101. short                gCurrentLevel = 128;
  102.  
  103. short                gNumDiamondsInMap = 0;    // Number of diamonds in the TileMap
  104. short                gNumDiamonds = 0;        // Number of diamonds sprite has collected
  105.  
  106. struct moveKeys        // Keeps track of which keys are up and which are down
  107. {
  108.     Boolean    up;
  109.     Boolean    right;
  110.     Boolean    down;
  111.     Boolean    left;
  112. } gKeys;
  113.  
  114.  
  115. ///--------------------------------------------------------------------------------------
  116. // Main
  117. ///--------------------------------------------------------------------------------------
  118.  
  119. void    main( void )
  120. {
  121.     Initialize(kNumberOfMoreMastersCalls);
  122.     
  123.     if (SWHasSystem7())
  124.     {
  125.         AllowKeyUpEvents();    // Part of SWGameUtils.c
  126.         SetCursor(*GetCursor(watchCursor));
  127.         
  128.         CreateSpriteWorld();
  129.         SetUpTiling();
  130.         CreateBallSprite();
  131.         CreateDiamondMeterSprite();
  132.         CreateMouseSprite();
  133.         
  134.         SetCursor(&qd.arrow);
  135.         HideCursor();
  136.         
  137.         SetUpAnimation();
  138.         RunAnimation();
  139.         ShutDown();
  140.         
  141.         RestoreEventMask();    // Call this after AllowKeyUpEvents
  142.     }
  143.     else
  144.     {
  145.         CantRunOnThisMachine();
  146.     }
  147. }
  148.  
  149.  
  150. ///--------------------------------------------------------------------------------------
  151. // CreateSpriteWorld
  152. ///--------------------------------------------------------------------------------------
  153.  
  154. void    CreateSpriteWorld( void )
  155. {
  156.     Rect        offscreenRect, worldRect, windRect;
  157.     OSErr        err;
  158.     WindowPeek    windowPeek;
  159.     WStateData    *wStateData;
  160.     
  161.     gWindowP = GetNewCWindow(129, NULL, (WindowPtr)-1L);
  162.     
  163.     if (gWindowP != NULL)
  164.     {
  165.             // Center window in screen
  166.         windRect = gWindowP->portRect;
  167.         if (qd.screenBits.bounds.bottom < 440 || qd.screenBits.bounds.right < 600)
  168.         {
  169.                 // We're running in 512x384, so make the window smaller so it can be moved
  170.             windRect.bottom -= 80;
  171.             windRect.right -= 80;
  172.             SizeWindow(gWindowP, windRect.right - windRect.left, 
  173.                         windRect.bottom - windRect.top, false);
  174.         }
  175.         CenterRect(&windRect, &qd.screenBits.bounds);
  176.         windRect.top += 10;
  177.         windRect.bottom += 10;
  178.         
  179.             // Make sure window is aligned to long-word boundaries (for 8-bit mode)
  180.         windRect.left = windRect.left>>2<<2;
  181.         
  182.         MoveWindow(gWindowP, windRect.left, windRect.top, false);
  183.         
  184.         ShowWindow(gWindowP);
  185.         SetPort(gWindowP);
  186.         
  187.         if (kInterlacedMode)
  188.             PaintRect(&gWindowP->portRect);    // Blacken window for Interlaced mode
  189.     }
  190.     else
  191.         CantFindResource();
  192.     
  193.         // Change window's standard size to its current size. (Used when zooming window.)
  194.     windowPeek = (WindowPeek)gWindowP;
  195.     wStateData = (WStateData *) *(windowPeek->dataHandle);
  196.     wStateData->stdState = (**(windowPeek->contRgn)).rgnBBox;
  197.  
  198.     
  199.     err = SWEnterSpriteWorld();
  200.     FatalError(err);
  201.     
  202.     
  203.     worldRect = gWindowP->portRect;
  204.     
  205.         // Set size of offscreen area
  206.     offscreenRect = worldRect;
  207.     OffsetRect(&offscreenRect, -offscreenRect.left, -offscreenRect.top);
  208.     offscreenRect.right = SW_MAX(offscreenRect.right, kMaxWindowWidth);
  209.     offscreenRect.bottom = SW_MAX(offscreenRect.bottom, kMaxWindowHeight);
  210.  
  211.         // Make offscreen area evenly divisible by tile width & height
  212.     if ( (offscreenRect.right/kTileWidth)*kTileWidth != offscreenRect.right)
  213.         offscreenRect.right = (offscreenRect.right/kTileWidth)*kTileWidth + kTileWidth;
  214.     
  215.     if ( (offscreenRect.bottom/kTileHeight)*kTileHeight != offscreenRect.bottom)
  216.         offscreenRect.bottom = (offscreenRect.bottom/kTileHeight)*kTileHeight + kTileHeight;
  217.     
  218.         // Create the scrolling sprite world
  219.     err = SWCreateSpriteWorldFromWindow(&gSpriteWorldP, (CWindowPtr)gWindowP, 
  220.             &worldRect, &offscreenRect, 0);
  221.     FatalError(err);
  222.     
  223.     
  224.             // Create the sprite layers
  225.     err = SWCreateSpriteLayer(&gSpriteLayerP);
  226.     FatalError(err);
  227.     err = SWCreateSpriteLayer(&gMouseSpriteLayerP);
  228.     FatalError(err);
  229.     
  230.         // add the layers to the world
  231.     SWAddSpriteLayer(gSpriteWorldP, gSpriteLayerP);            // Bottom layer
  232.     SWAddSpriteLayer(gSpriteWorldP, gMouseSpriteLayerP);    // Top layer
  233.  
  234.     
  235.     
  236.         // Determine what DrawProcs to use
  237.     if (gSpriteWorldP->pixelDepth == 8)        // 256 colors
  238.     {
  239.         if (kInterlacedMode)
  240.         {
  241.             gSpriteDrawProc = BP8BitInterlacedMaskDrawProc;
  242.             gScreenDrawProc = BP8BitInterlacedRectDrawProc;
  243.             gDoubleRectDrawProc = BP8BitInterlacedDoubleRectDrawProc;
  244.             SWSetTileMaskDrawProc(gSpriteWorldP, BP8BitInterlacedPartialMaskDrawProc);
  245.         }
  246.         else
  247.         {
  248.             gSpriteDrawProc = BlitPixie8BitMaskDrawProc;
  249.             gScreenDrawProc = BlitPixie8BitRectDrawProc;
  250.             gDoubleRectDrawProc = BlitPixie8BitDoubleRectDrawProc;
  251.             SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixie8BitPartialMaskDrawProc);
  252.         }
  253.     }
  254.     else if ( !(SW_PPC && gSpriteWorldP->pixelDepth < 8) )    // Not 256 colors
  255.     {
  256.             // Use interlaced drawProcs unless in B&W, where interlacing is ugly
  257.         if (kInterlacedMode && gSpriteWorldP->pixelDepth > 2)
  258.         {
  259.             gSpriteDrawProc = BPAllBitInterlacedMaskDrawProc;
  260.             gScreenDrawProc = BPAllBitInterlacedRectDrawProc;
  261.             SWSetTileMaskDrawProc(gSpriteWorldP, BPAllBitInterlacedPartialMaskDrawProc);
  262.             if (gSpriteWorldP->pixelDepth == 16)
  263.                 gDoubleRectDrawProc = BP16BitInterlacedDoubleRectDrawProc;
  264.         }
  265.         else
  266.         {
  267.             gSpriteDrawProc = BlitPixieAllBitMaskDrawProc;
  268.             gScreenDrawProc = BlitPixieAllBitRectDrawProc;
  269.             SWSetTileMaskDrawProc(gSpriteWorldP, BlitPixieAllBitPartialMaskDrawProc);
  270.             if (gSpriteWorldP->pixelDepth == 16)
  271.                 gDoubleRectDrawProc = BlitPixie16BitDoubleRectDrawProc;
  272.         }
  273.     }
  274.     else
  275.     {
  276.         gSpriteDrawProc = SWStdSpriteDrawProc;
  277.         gScreenDrawProc = SWStdWorldDrawProc;
  278.         gDoubleRectDrawProc = NULL;
  279.     }
  280. }
  281.  
  282.  
  283. ///--------------------------------------------------------------------------------------
  284. // SetUpTiling
  285. ///--------------------------------------------------------------------------------------
  286.  
  287. void    SetUpTiling( void )
  288. {    
  289.     OSErr        err;
  290.  
  291.     err = SWInitTiling(gSpriteWorldP, kTileHeight, kTileWidth, kMaxNumTiles);
  292.     FatalError(err);
  293.     
  294.     err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  295.     FatalError(err);
  296.     
  297.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  298.     gTileMap = gTileMapStructP->tileMap;
  299.  
  300.         // Load the tiles
  301.     err = SWLoadTilesFromPictResource(
  302.         gSpriteWorldP, 
  303.         kFirstWallTile,            // startTileID 
  304.         kLastExitTile,            // endTileID
  305.         kTilePictResID,            // pictResID
  306.         0,                        // maskResID
  307.         kNoMask,                // maskType
  308.         0,                        // horizBorderWidth
  309.         0);                        // vertBorderHeight
  310.     FatalError(err);
  311.     
  312.     
  313.     CountDiamonds();
  314. }
  315.  
  316.  
  317. ///--------------------------------------------------------------------------------------
  318. // CountDiamonds - Counts the number of diamonds in the TileMap
  319. ///--------------------------------------------------------------------------------------
  320.  
  321. void    CountDiamonds( void )
  322. {
  323.     short    row, col;
  324.     
  325.     gNumDiamondsInMap = 0;
  326.     gNumDiamonds = 0;
  327.     
  328.     for (row = 0; row < gSpriteWorldP->tileLayerArray[0]->numRows; row++)
  329.     {
  330.         for (col = 0; col < gSpriteWorldP->tileLayerArray[0]->numCols; col++)
  331.         {
  332.             if (gTileMap[row][col] == kDiamondTile)
  333.                 gNumDiamondsInMap++;
  334.         }
  335.     }
  336. }
  337.     
  338.  
  339. ///--------------------------------------------------------------------------------------
  340. // CreateBallSprite
  341. ///--------------------------------------------------------------------------------------
  342.  
  343. void    CreateBallSprite( void )
  344. {
  345.     OSErr                err;
  346.     
  347.         // Create the ball sprite
  348.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gSimpleSpriteP, NULL, 
  349.             128, 1, kFatMask);    
  350.     FatalError(err);
  351.     
  352.         // Set up the ball sprite
  353.     SWAddSprite(gSpriteLayerP, gSimpleSpriteP);
  354.     SWSetSpriteMoveProc(gSimpleSpriteP, KeySpriteMoveProc);
  355.     SWSetSpriteLocation(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  356.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  357.     SWSetSpriteDrawProc(gSimpleSpriteP, gSpriteDrawProc);
  358. }
  359.  
  360.  
  361. ///--------------------------------------------------------------------------------------
  362. // CreateDiamondMeterSprite
  363. ///--------------------------------------------------------------------------------------
  364.  
  365. void    CreateDiamondMeterSprite( void )
  366. {
  367.     OSErr                err;
  368.     
  369.         // Create the diamond meter sprite
  370.     err = SWCreateSpriteFromPictResource(gSpriteWorldP, &gDiamondMeterSpriteP, NULL,
  371.                 kSpritePictResID, kSpritePictResID, 1, kPixelMask);
  372.     FatalError(err);
  373.     
  374.     SWAddSprite(gSpriteLayerP, gDiamondMeterSpriteP);
  375.     SWSetSpriteDrawProc(gDiamondMeterSpriteP, gSpriteDrawProc);
  376. }
  377.  
  378.  
  379. ///--------------------------------------------------------------------------------------
  380. // CreateMouseSprite
  381. ///--------------------------------------------------------------------------------------
  382.  
  383. void    CreateMouseSprite( void )
  384. {
  385.     OSErr                err;
  386.     
  387.         // Create the mouse sprite
  388.     err = SWCreateSpriteFromCicnResource(gSpriteWorldP, &gMouseSpriteP, NULL, 
  389.             130, 1, kPixelMask);    
  390.     FatalError(err);
  391.  
  392.     SWAddSprite(gMouseSpriteLayerP, gMouseSpriteP);
  393.     SWSetSpriteDrawProc(gMouseSpriteP, gSpriteDrawProc);
  394. }
  395.  
  396.  
  397. ///--------------------------------------------------------------------------------------
  398. // SetUpAnimation
  399. ///--------------------------------------------------------------------------------------
  400.  
  401. void    SetUpAnimation( void )
  402. {
  403.     Rect        moveBoundsRect, worldRect;
  404.     
  405.     SWLockSpriteWorld(gSpriteWorldP);
  406.     
  407.         // Set up data used by the SmoothScrollingWorldMoveProc
  408.     gScreenMidRect = gSimpleSpriteP->curFrameP->frameRect;
  409.     worldRect = gSpriteWorldP->windRect;
  410.     OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  411.     CenterRect( &gScreenMidRect, &worldRect );
  412.     
  413.     SWSetSpriteWorldMaxFPS(gSpriteWorldP, kMaxFPS);
  414.     SWSyncSpriteWorldToVBL(gSpriteWorldP, kSyncToVBL);
  415.     SWSetCleanUpSpriteWorld(gSpriteWorldP);
  416.     
  417.         // movement boundary = size of tileMap
  418.     SetRect(&moveBoundsRect, 0, 0, 
  419.         gSpriteWorldP->tileLayerArray[0]->numCols * gSpriteWorldP->tileWidth, 
  420.         gSpriteWorldP->tileLayerArray[0]->numRows * gSpriteWorldP->tileHeight);
  421.     
  422.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  423.     SWSetScrollingWorldMoveProc(gSpriteWorldP, SmoothScrollingWorldMoveProc, gSimpleSpriteP);
  424.     
  425.     SWSetTileChangeProc(gSpriteWorldP, TileChangeProc);
  426.     
  427.         // Move visScrollRect to starting sprite position
  428.     SWMoveVisScrollRect(gSpriteWorldP, 
  429.         gSpriteWorldP->followSpriteP->destFrameRect.left - gSpriteWorldP->backRect.right/2,
  430.         gSpriteWorldP->followSpriteP->destFrameRect.top - gSpriteWorldP->backRect.bottom/2);
  431.     
  432.         // Set starting position of diamond meter sprite
  433.     DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  434.  
  435.     SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  436.     SWSetSpriteWorldOffscreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  437.     SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  438.     
  439.         // Make sure CopyBits, if used, doesn't try to colorize things
  440.     SWSetPortToWindow(gSpriteWorldP);
  441.     ForeColor(blackColor);
  442.     BackColor(whiteColor);
  443.     
  444.     SWSetPortToWorkArea(gSpriteWorldP);
  445.     ForeColor(blackColor);
  446.     PaintRect(&gSpriteWorldP->backRect);
  447.     SWDrawTilesInBackground(gSpriteWorldP);
  448.     SWUpdateScrollingSpriteWorld(gSpriteWorldP, true);
  449.     ShowCursor();
  450. }
  451.  
  452.  
  453. ///--------------------------------------------------------------------------------------
  454. //  RunAnimation
  455. ///--------------------------------------------------------------------------------------
  456.  
  457. void    RunAnimation( void )
  458. {
  459.     EventRecord            event;
  460.     unsigned long        frames;
  461.     
  462.     frames = 0;
  463.     StartTimer();
  464.  
  465.     while (!gDone)
  466.     {
  467.         if ( WaitNextEvent(everyEvent, &event, 0L, NULL) )
  468.             DispatchEvent(&event);
  469.  
  470.             // Make sure window wasn't "rolled up" with WindowShade
  471.         if ( !EmptyRgn( gWindowP->visRgn ) )
  472.         {
  473.             SWProcessScrollingSpriteWorld(gSpriteWorldP);
  474.     
  475.                 // Move diamond meter & mouse sprites to new visScrollRect location
  476.             DiamondMeterSpriteMoveProc(gDiamondMeterSpriteP);
  477.             MouseSpriteMoveProc(gMouseSpriteP);
  478.                 
  479.             SWAnimateScrollingSpriteWorld(gSpriteWorldP);
  480.             
  481.             if (gSpriteWorldP->frameHasOccurred)
  482.             {
  483.                 frames++;
  484.                 
  485.                 if (gSpriteHitExit)
  486.                     AdvanceLevel();
  487.             }
  488.         }
  489.     }
  490.     
  491.     ShowResults(frames);
  492. }
  493.  
  494. ///--------------------------------------------------------------------------------------
  495. //  DispatchEvent
  496. ///--------------------------------------------------------------------------------------
  497.  
  498. void DispatchEvent(EventRecord* event)
  499. {
  500.     short            theKey, theChar;
  501.     Boolean            isDown;
  502.     
  503.     switch(event->what)
  504.     {
  505.         case mouseDown:
  506.             HandleMouseDown( event );
  507.             break;
  508.         case mouseUp:
  509.             break;
  510.         case keyUp:
  511.         case keyDown:
  512.         case autoKey:
  513.             theKey = (event->message & keyCodeMask) >> 8;
  514.             theChar = event->message & charCodeMask;
  515.             isDown = (event->what != keyUp);
  516.             
  517.             if ( (theKey == kLeftArrowKey) || (theKey == kLeftKeyPad) )
  518.                 gKeys.left = isDown;
  519.             else if ( (theKey == kRightArrowKey) || (theKey == kRightKeyPad) )
  520.                 gKeys.right = isDown;
  521.             else if ( (theKey == kDownArrowKey) || (theKey == kDownKeyPad) )
  522.                 gKeys.down = isDown;
  523.             else if ( (theKey == kUpArrowKey) || (theKey == kUpKeyPad) )
  524.                 gKeys.up = isDown;
  525.             else if ( (theKey == kEscKey) || (theChar == 'Q') || (theChar == 'q') )
  526.                 gDone = true;
  527.             break;
  528.             break;
  529.         case updateEvt:
  530.             break;
  531.         case diskEvt:
  532.             break;
  533.         case activateEvt:
  534.             break;
  535.         case networkEvt:
  536.             break;
  537.         case driverEvt:
  538.             break;
  539.         case app1Evt:
  540.             break;
  541.         case app2Evt:
  542.             break;
  543.         case app3Evt:
  544.             break;
  545.         case osEvt:
  546.             if ( ( event->message & suspendResumeMessage ) == resumeFlag )
  547.             {
  548.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, gScreenDrawProc);
  549.                 SWSetDoubleRectDrawProc(gSpriteWorldP, gDoubleRectDrawProc);
  550.             }
  551.             else
  552.             {
  553.                 SWSetSpriteWorldScreenDrawProc(gSpriteWorldP, SWStdWorldDrawProc);
  554.                 SWSetDoubleRectDrawProc(gSpriteWorldP, NULL);
  555.             }
  556.             break;
  557.         case kHighLevelEvent:
  558.             break;
  559.         default:
  560.         break;
  561.     }
  562. }
  563.  
  564.  
  565. ///--------------------------------------------------------------------------------------
  566. //  HandleMouseDown
  567. ///--------------------------------------------------------------------------------------
  568.  
  569. void    HandleMouseDown( EventRecord *eventPtr )
  570. {
  571.     WindowPtr        theWindow;
  572.     Rect            windRect;
  573.     short            thePart;
  574.     Point            thePoint;
  575.     long            windowSize;
  576.     Rect            worldRect;
  577.     
  578.     
  579.     thePoint = eventPtr->where;
  580.     thePart = FindWindow( thePoint, &theWindow );
  581.  
  582.     switch ( thePart )
  583.     {
  584.         case inSysWindow : 
  585.             SystemClick( eventPtr, theWindow );
  586.             break;
  587.         case inDrag:
  588.             DragWindow( theWindow, thePoint, &((**(GetGrayRgn())).rgnBBox) );
  589.             windRect = (*((WindowPeek)gWindowP)->contRgn)->rgnBBox;
  590.             
  591.                 // Align window to long word bounds
  592.             if (gSpriteWorldP->pixelDepth == 16)
  593.             {
  594.                 MoveWindow(gWindowP, windRect.left>>1<<1, windRect.top, false);
  595.             }
  596.             else if (gSpriteWorldP->pixelDepth <= 8)
  597.             {
  598.                 MoveWindow(gWindowP, windRect.left>>2<<2, windRect.top, false);
  599.             }
  600.             
  601.             SWWindowMoved( gSpriteWorldP );
  602.             break;
  603.         case inZoomOut:
  604.         case inZoomIn:
  605.             if ( TrackBox(theWindow, thePoint, thePart) )
  606.             {
  607.                 ZoomWindow(theWindow, thePart, true);
  608.                 SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  609.                 SWDrawTilesInBackground( gSpriteWorldP );
  610.                 SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  611.             
  612.                     // Reset data used by SmoothScrollingWorldMoveProc
  613.                 worldRect = gSpriteWorldP->windRect;
  614.                 OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  615.                 CenterRect( &gScreenMidRect, &worldRect );
  616.             }
  617.             break;
  618.         case inMenuBar:
  619.             break;
  620.         case inGoAway:
  621.             if ( TrackGoAway(theWindow, thePoint) )
  622.                 gDone = true;
  623.             break;
  624.         case inGrow:
  625.             SetRect(&windRect, 80, 80, 
  626.                 gSpriteWorldP->originalBackRect.right - gSpriteWorldP->originalBackRect.left+1, 
  627.                 gSpriteWorldP->originalBackRect.bottom - gSpriteWorldP->originalBackRect.top+1); 
  628.             windowSize = GrowWindow( theWindow, eventPtr->where, &windRect );
  629.             SizeWindow( theWindow, LoWord(windowSize), HiWord(windowSize), true);
  630.             SWChangeWorldRect( gSpriteWorldP, &theWindow->portRect, false);
  631.             SWDrawTilesInBackground( gSpriteWorldP );
  632.             SWUpdateScrollingSpriteWorld( gSpriteWorldP , false );
  633.             
  634.                 // Reset data used by SmoothScrollingWorldMoveProc
  635.             worldRect = gSpriteWorldP->windRect;
  636.             OffsetRect(&worldRect, -worldRect.left, -worldRect.top);
  637.             CenterRect( &gScreenMidRect, &worldRect );
  638.             break;
  639.         case inContent:
  640.             break;
  641.     }
  642. }
  643.  
  644.  
  645. ///--------------------------------------------------------------------------------------
  646. //  ShutDown (clean up and dispose of the SpriteWorld)
  647. ///--------------------------------------------------------------------------------------
  648.  
  649. void    ShutDown( void )
  650. {
  651.     SWDisposeSpriteWorld(&gSpriteWorldP);
  652.     SWExitSpriteWorld();
  653.     
  654.     FlushEvents(everyEvent, 0);
  655.     ShowCursor();
  656. }
  657.  
  658.  
  659. ///--------------------------------------------------------------------------------------
  660. //  TileChangeProc
  661. ///--------------------------------------------------------------------------------------
  662.  
  663. SW_FUNC void TileChangeProc(
  664.     SpriteWorldPtr spriteWorldP)
  665. {
  666.     short            curImage;
  667.     static short    diamondDelay = 0, exitDelay = 0;
  668.     static short    oldTicks = 0;
  669.     short            ticksPassed, ticks;
  670.     
  671.         // Initialize oldTicks the first time this function is called
  672.     if (oldTicks == 0)
  673.         oldTicks = TickCount();
  674.     
  675.     ticks = TickCount();
  676.     ticksPassed = ticks - oldTicks;        // Number of ticks passed since last call
  677.     oldTicks = ticks;
  678.     
  679.     
  680.         // kDiamondTile
  681.     diamondDelay += ticksPassed;
  682.     if (diamondDelay >= kDiamondFrameRate)
  683.     {
  684.         curImage = spriteWorldP->curTileImage[kDiamondTile];
  685.         if (curImage < kLastDiamondTile)
  686.             curImage++;
  687.         else
  688.             curImage = kDiamondTile;
  689.         
  690.         SWChangeTileImage(spriteWorldP, kDiamondTile, curImage);
  691.         diamondDelay = 0;
  692.     }
  693.     
  694.     
  695.         // Flash exit tile if all diamonds have been collected
  696.     exitDelay += ticksPassed;
  697.     if (exitDelay >= kExitFrameRate)
  698.     {
  699.         if  (!kRequireDiamondsToExit || gNumDiamonds == gNumDiamondsInMap)
  700.         {
  701.             curImage = spriteWorldP->curTileImage[ kFirstExitTile ];
  702.             if ( curImage < kLastExitTile )
  703.                 curImage++;
  704.             else
  705.                 curImage = kFirstExitTile;
  706.             
  707.             SWChangeTileImage( spriteWorldP, kFirstExitTile, curImage );
  708.         }
  709.         exitDelay = 0;
  710.     }
  711. }
  712.  
  713. ///--------------------------------------------------------------------------------------
  714. //  KeySpriteMoveProc
  715. ///--------------------------------------------------------------------------------------
  716.  
  717. SW_FUNC void KeySpriteMoveProc(SpritePtr srcSpriteP)
  718. {
  719.     short    row, col;
  720.     short    rowDelta, colDelta;
  721.     short    tile;
  722.     
  723.     
  724.     row = srcSpriteP->destFrameRect.top / kTileHeight;
  725.     col = srcSpriteP->destFrameRect.left / kTileWidth;
  726.  
  727.     if (row * kTileHeight == srcSpriteP->destFrameRect.top &&
  728.         col * kTileWidth == srcSpriteP->destFrameRect.left)
  729.     {
  730.         tile = gTileMap[row][col];
  731.         
  732.             // Leave black trail behind sprite
  733.         if ( (tile >= kFirstGrassTile && tile <= kLastGrassTile) || tile == kDiamondTile)
  734.             SWDrawTile(gSpriteWorldP, 0, row, col, kBlackTile);
  735.             
  736.         if (tile == kDiamondTile)
  737.         {
  738.             gNumDiamonds++;            // Increase number of diamonds sprite has collected
  739.             UpdateDiamondMeter();    // Update meter
  740.         }
  741.         else if (tile == kFirstExitTile)
  742.         {
  743.             if  (!kRequireDiamondsToExit || gNumDiamonds == gNumDiamondsInMap)
  744.             {
  745.                 gSpriteHitExit = true;
  746.                 return;
  747.             }
  748.         }
  749.         
  750.  
  751.         rowDelta = 0;
  752.         colDelta = 0;
  753.         
  754.         if (gKeys.left)
  755.             colDelta = -1;
  756.         else if (gKeys.right)
  757.             colDelta = 1;
  758.         else if (gKeys.up)
  759.             rowDelta = -1;
  760.         else if (gKeys.down)
  761.             rowDelta = 1;
  762.         
  763.                 
  764.         
  765.         tile = gTileMap[row + rowDelta][col + colDelta];
  766.         
  767.         if (tile < kFirstWallTile || tile > kLastWallTile)
  768.         {
  769.             srcSpriteP->vertMoveDelta = rowDelta * kSpriteMoveDelta;
  770.             srcSpriteP->horizMoveDelta = colDelta * kSpriteMoveDelta;
  771.         }
  772.         else
  773.         {
  774.             srcSpriteP->vertMoveDelta = 0;
  775.             srcSpriteP->horizMoveDelta = 0;
  776.         }
  777.     }
  778.     
  779.     SWOffsetSprite(srcSpriteP, srcSpriteP->horizMoveDelta, srcSpriteP->vertMoveDelta);
  780. }
  781.  
  782.  
  783. ///--------------------------------------------------------------------------------------
  784. //  MouseSpriteMoveProc
  785. ///--------------------------------------------------------------------------------------
  786.  
  787. SW_FUNC void MouseSpriteMoveProc(SpritePtr srcSpriteP)
  788. {
  789.     Point                mousePoint;
  790.     
  791.         // Get mouse coordinates local to the window
  792.     SetPort(gWindowP);
  793.     GetMouse(&mousePoint);
  794.     
  795.         // Subtract any offset from worldRect to window if a worldRect is used
  796.     mousePoint.h -= gSpriteWorldP->windRect.left;
  797.     mousePoint.v -= gSpriteWorldP->windRect.top;
  798.     
  799.     SWMoveSprite(srcSpriteP, 
  800.         mousePoint.h - 1 + gSpriteWorldP->visScrollRect.left, 
  801.         mousePoint.v - 1 + gSpriteWorldP->visScrollRect.top);
  802. }
  803.  
  804.  
  805. ///--------------------------------------------------------------------------------------
  806. //  DiamondMeterSpriteMoveProc - not installed as a MoveProc, but called directly
  807. ///--------------------------------------------------------------------------------------
  808.  
  809. SW_FUNC void DiamondMeterSpriteMoveProc(SpritePtr srcSpriteP)
  810. {
  811.         // Move sprite to top-left corner of current visScrollRect location
  812.     SWMoveSprite(srcSpriteP, 
  813.         gSpriteWorldP->visScrollRect.left + 10, 
  814.         gSpriteWorldP->visScrollRect.top + 10);
  815. }
  816.  
  817.  
  818. ///--------------------------------------------------------------------------------------
  819. //  UpdateDiamondMeter - change the meter Sprite's image and mask
  820. ///--------------------------------------------------------------------------------------
  821.  
  822. SW_FUNC void UpdateDiamondMeter( void )
  823. {
  824.     double    percent;
  825.     Rect    meterRect;
  826.     
  827.     percent = (double)gNumDiamonds / gNumDiamondsInMap;
  828.     
  829.     SetRect(&meterRect, 17, 2, (108 * percent) + 17, 14);
  830.     
  831.     
  832.         // Set port to our sprite's framePort GWorld
  833.     SetGWorld(gDiamondMeterSpriteP->curFrameP->framePort, nil);
  834.     
  835.     ForeColor(magentaColor);
  836.     PaintRect(&meterRect);
  837.     
  838.     
  839.         // Set port to our sprite's pixel mask GWorld
  840.     SetGWorld(gDiamondMeterSpriteP->curFrameP->maskPort, nil);
  841.     
  842.         // Mask image is inverted when in 8-bit or less
  843.     if (gSpriteWorldP->pixelDepth <= 8)
  844.         ForeColor(whiteColor);
  845.     else
  846.         ForeColor(blackColor);
  847.     
  848.     PaintRect(&meterRect);
  849.     
  850.     
  851.         // Set sprite to be redrawn, since we've changed its image
  852.     gDiamondMeterSpriteP->needsToBeDrawn = true;
  853. }
  854.  
  855.  
  856. ///--------------------------------------------------------------------------------------
  857. //  SmoothScrollingWorldMoveProc - our scrolling WorldMoveProc
  858. ///--------------------------------------------------------------------------------------
  859.  
  860. SW_FUNC void SmoothScrollingWorldMoveProc(
  861.     SpriteWorldPtr spriteWorldP,
  862.     SpritePtr followSpriteP)
  863. {    
  864.     short    screenMidRectTop, screenMidRectLeft;
  865.     
  866.     screenMidRectTop = gScreenMidRect.top + spriteWorldP->visScrollRect.top;
  867.     screenMidRectLeft = gScreenMidRect.left + spriteWorldP->visScrollRect.left;
  868.     
  869.     
  870.     spriteWorldP->horizScrollDelta = (kSpriteMoveDelta * 
  871.         (followSpriteP->destFrameRect.left - screenMidRectLeft) ) / kSpriteMoveDistance;
  872.     
  873.     spriteWorldP->vertScrollDelta = (kSpriteMoveDelta * 
  874.         (followSpriteP->destFrameRect.top - screenMidRectTop) ) / kSpriteMoveDistance;
  875.     
  876.     if (kInterlacedMode)
  877.         spriteWorldP->vertScrollDelta = spriteWorldP->vertScrollDelta>>1<<1;
  878. }
  879.  
  880.  
  881. ///--------------------------------------------------------------------------------------
  882. //  AdvanceLevel
  883. ///--------------------------------------------------------------------------------------
  884.  
  885. void    AdvanceLevel( void )
  886. {
  887.     Rect            moveBoundsRect;
  888.     unsigned long    junkTime;
  889.     OSErr            err;
  890.     
  891.     gCurrentLevel++;
  892.     gSpriteHitExit = false;
  893.     
  894.     SWDisposeTileMap(&gTileMapStructP);
  895.     err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  896.     if (err)
  897.     {
  898.         gCurrentLevel = 128;
  899.         err = SWLoadTileMap(&gTileMapStructP, gCurrentLevel);
  900.         FatalError(err);
  901.     }
  902.     
  903.     gTileMap = gTileMapStructP->tileMap;
  904.     SWInstallTileMap(gSpriteWorldP, gTileMapStructP, 0);
  905.     
  906.         // Reset scrolling moveBounds for new TileMap
  907.     SetRect(&moveBoundsRect, 0, 0, 
  908.         gTileMapStructP->numCols * kTileWidth, 
  909.         gTileMapStructP->numRows * kTileHeight);
  910.     SWSetScrollingWorldMoveBounds(gSpriteWorldP, &moveBoundsRect);
  911.     
  912.     Delay(15, &junkTime);
  913.     
  914.     CountDiamonds();
  915.     
  916.         // Update Diamond Meter Sprite, since we've changed its frame and mask
  917.     SWUpdateSpriteFromPictResource(gDiamondMeterSpriteP, kSpritePictResID);
  918.     SWUpdateFrameMasks(gSpriteWorldP, gDiamondMeterSpriteP->curFrameP);
  919.     
  920.     SWSetSpriteMoveDelta(gSimpleSpriteP, 0, 0);
  921.     SWMoveSprite(gSimpleSpriteP, kStartCol * kTileWidth, kStartRow * kTileHeight);
  922.     SWMoveVisScrollRect(gSpriteWorldP, 0, 0);
  923.     
  924.     SWResetCurrentTileImages(gSpriteWorldP);
  925.     SWDrawTilesInBackground(gSpriteWorldP);
  926.     SWUpdateSpriteWorld(gSpriteWorldP, false);
  927. }